#include "gdkmacosclipboard-private.h"
#include "gdkmacosdisplay-private.h"
+#include "gdkmacosdrop-private.h"
#include "gdkmacosmonitor-private.h"
#include "gdkmacossurface-private.h"
#include "gdkmacospopupsurface-private.h"
-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
- return NSDragOperationNone;
+ NSPoint location = [sender draggingLocation];
+ NSDragOperation ret;
+ GdkMacosDrop *drop;
+
+ if (!(drop = _gdk_macos_drop_new ([self gdkSurface], sender)))
+ return NSDragOperationNone;
+
+ _gdk_macos_display_set_drop ([self gdkDisplay],
+ [sender draggingSequenceNumber],
+ GDK_DROP (drop));
+
+ gdk_drop_emit_enter_event (GDK_DROP (drop),
+ TRUE,
+ location.x,
+ GDK_SURFACE (gdk_surface)->height - location.y,
+ GDK_CURRENT_TIME);
+
+ ret = _gdk_macos_drop_operation (drop);
+
+ g_object_unref (drop);
+
+ return ret;
}
-(void)draggingEnded:(id <NSDraggingInfo>)sender
{
+ _gdk_macos_display_set_drop ([self gdkDisplay], [sender draggingSequenceNumber], NULL);
}
-(void)draggingExited:(id <NSDraggingInfo>)sender
{
+ NSInteger sequence_number = [sender draggingSequenceNumber];
+ GdkDrop *drop = _gdk_macos_display_find_drop ([self gdkDisplay], sequence_number);
+
+ if (drop != NULL)
+ gdk_drop_emit_leave_event (drop, TRUE, GDK_CURRENT_TIME);
+
+ _gdk_macos_display_set_drop ([self gdkDisplay], sequence_number, NULL);
}
-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender
{
- return NSDragOperationNone;
+ NSInteger sequence_number = [sender draggingSequenceNumber];
+ GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
+ GdkDrop *drop = _gdk_macos_display_find_drop (GDK_MACOS_DISPLAY (display), sequence_number);
+ NSPoint location = [sender draggingLocation];
+
+ if (drop == NULL)
+ return NSDragOperationNone;
+
+ _gdk_macos_drop_update_actions (GDK_MACOS_DROP (drop), sender);
+
+ gdk_drop_emit_motion_event (drop,
+ TRUE,
+ location.x,
+ GDK_SURFACE (gdk_surface)->height - location.y,
+ GDK_CURRENT_TIME);
+
+ return _gdk_macos_drop_operation (GDK_MACOS_DROP (drop));
}
-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender
{
- return YES;
+ NSInteger sequence_number = [sender draggingSequenceNumber];
+ GdkDisplay *display = gdk_surface_get_display (GDK_SURFACE (gdk_surface));
+ GdkDrop *drop = _gdk_macos_display_find_drop (GDK_MACOS_DISPLAY (display), sequence_number);
+ NSPoint location = [sender draggingLocation];
+
+ if (drop == NULL)
+ return NO;
+
+ gdk_drop_emit_drop_event (drop,
+ TRUE,
+ location.x,
+ GDK_SURFACE (gdk_surface)->height - location.y,
+ GDK_CURRENT_TIME);
+
+ gdk_drop_emit_leave_event (drop, TRUE, GDK_CURRENT_TIME);
+
+ return GDK_MACOS_DROP (drop)->finish_action != 0;
}
-(BOOL)wantsPeriodicDraggingUpdates
/* The surface that is receiving keyboard events */
GdkMacosSurface *keyboard_surface;
+ /* [NSDraggingInfo draggingSequenceNumber] to GdkMacosDr(ag,op) */
+ GHashTable *active_drags;
+ GHashTable *active_drops;
+
/* Used to translate from quartz coordinate space to GDK */
int width;
int height;
int x,
int y);
NSEvent *_gdk_macos_display_get_nsevent (GdkEvent *event);
+GdkDrag *_gdk_macos_display_find_drag (GdkMacosDisplay *self,
+ NSInteger sequence_number);
+GdkDrop *_gdk_macos_display_find_drop (GdkMacosDisplay *self,
+ NSInteger sequence_number);
+void _gdk_macos_display_set_drag (GdkMacosDisplay *self,
+ NSInteger sequence_number,
+ GdkDrag *drag);
+void _gdk_macos_display_set_drop (GdkMacosDisplay *self,
+ NSInteger sequence_number,
+ GdkDrop *drop);
G_END_DECLS
#include "gdkmacoscairocontext-private.h"
#include "gdkmacoseventsource-private.h"
#include "gdkmacosdisplay-private.h"
+#include "gdkmacosdrag-private.h"
+#include "gdkmacosdrop-private.h"
#include "gdkmacosglcontext-private.h"
#include "gdkmacoskeymap-private.h"
#include "gdkmacosmonitor-private.h"
CFSTR ("NSUserDefaultsDidChangeNotification"),
NULL);
+ g_clear_pointer (&self->active_drags, g_hash_table_unref);
+ g_clear_pointer (&self->active_drops, g_hash_table_unref);
g_clear_object (&GDK_DISPLAY (self)->clipboard);
g_clear_pointer (&self->frame_source, g_source_unref);
g_clear_object (&self->monitors);
gdk_macos_display_init (GdkMacosDisplay *self)
{
self->monitors = g_list_store_new (GDK_TYPE_MONITOR);
+ self->active_drags = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
+ self->active_drops = g_hash_table_new_full (NULL, NULL, NULL, g_object_unref);
gdk_display_set_composited (GDK_DISPLAY (self), TRUE);
gdk_display_set_input_shapes (GDK_DISPLAY (self), FALSE);
return NULL;
}
+
+GdkDrag *
+_gdk_macos_display_find_drag (GdkMacosDisplay *self,
+ NSInteger sequence_number)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+
+ return g_hash_table_lookup (self->active_drags, GSIZE_TO_POINTER (sequence_number));
+}
+
+void
+_gdk_macos_display_set_drag (GdkMacosDisplay *self,
+ NSInteger sequence_number,
+ GdkDrag *drag)
+{
+ g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+ g_return_if_fail (!drag || GDK_IS_MACOS_DRAG (drag));
+
+ if (drag)
+ g_hash_table_insert (self->active_drags,
+ GSIZE_TO_POINTER (sequence_number),
+ g_object_ref (drag));
+ else
+ g_hash_table_remove (self->active_drags,
+ GSIZE_TO_POINTER (sequence_number));
+}
+
+GdkDrop *
+_gdk_macos_display_find_drop (GdkMacosDisplay *self,
+ NSInteger sequence_number)
+{
+ g_return_val_if_fail (GDK_IS_MACOS_DISPLAY (self), NULL);
+
+ return g_hash_table_lookup (self->active_drops, GSIZE_TO_POINTER (sequence_number));
+}
+
+void
+_gdk_macos_display_set_drop (GdkMacosDisplay *self,
+ NSInteger sequence_number,
+ GdkDrop *drop)
+{
+ g_return_if_fail (GDK_IS_MACOS_DISPLAY (self));
+ g_return_if_fail (!drop || GDK_IS_MACOS_DROP (drop));
+
+ if (drop)
+ g_hash_table_insert (self->active_drops,
+ GSIZE_TO_POINTER (sequence_number),
+ g_object_ref (drop));
+ else
+ g_hash_table_remove (self->active_drops,
+ GSIZE_TO_POINTER (sequence_number));
+}
--- /dev/null
+/*
+ * Copyright © 2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef __GDK_MACOS_DROP_PRIVATE_H__
+#define __GDK_MACOS_DROP_PRIVATE_H__
+
+#include <AppKit/AppKit.h>
+
+#include "gdkdropprivate.h"
+
+#include "gdkmacossurface-private.h"
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_MACOS_DROP (gdk_macos_drop_get_type ())
+#define GDK_MACOS_DROP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_MACOS_DROP, GdkMacosDrop))
+#define GDK_MACOS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_MACOS_DROP, GdkMacosDropClass))
+#define GDK_IS_MACOS_DROP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_MACOS_DROP))
+#define GDK_IS_MACOS_DROP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_MACOS_DROP))
+#define GDK_MACOS_DROP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_MACOS_DROP, GdkMacosDropClass))
+
+typedef struct _GdkMacosDrop GdkMacosDrop;
+typedef struct _GdkMacosDropClass GdkMacosDropClass;
+
+struct _GdkMacosDrop
+{
+ GdkDrop parent_instance;
+
+ NSPasteboard *pasteboard;
+
+ GdkDragAction all_actions;
+ GdkDragAction preferred_action;
+ GdkDragAction finish_action;
+};
+
+struct _GdkMacosDropClass
+{
+ GdkDropClass parent_class;
+};
+
+GType gdk_macos_drop_get_type (void) G_GNUC_CONST;
+GdkMacosDrop *_gdk_macos_drop_new (GdkMacosSurface *surface,
+ id<NSDraggingInfo> info);
+NSDragOperation _gdk_macos_drop_operation (GdkMacosDrop *self);
+void _gdk_macos_drop_update_actions (GdkMacosDrop *self,
+ id<NSDraggingInfo> info);
+
+G_END_DECLS
+
+#endif /* __GDK_MACOS_DROP_PRIVATE_H__ */
--- /dev/null
+/*
+ * Copyright © 2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gdkmacosclipboard-private.h"
+#include "gdkmacosdisplay-private.h"
+#include "gdkmacosdrag-private.h"
+#include "gdkmacosdrop-private.h"
+
+G_DEFINE_TYPE (GdkMacosDrop, gdk_macos_drop, GDK_TYPE_DROP)
+
+static void
+gdk_macos_drop_status (GdkDrop *drop,
+ GdkDragAction actions,
+ GdkDragAction preferred)
+{
+ GdkMacosDrop *self = (GdkMacosDrop *)drop;
+
+ g_assert (GDK_IS_MACOS_DROP (self));
+
+ self->all_actions = actions;
+ self->preferred_action = preferred;
+}
+
+static void
+gdk_macos_drop_read_async (GdkDrop *drop,
+ GdkContentFormats *content_formats,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ _gdk_macos_pasteboard_read_async (G_OBJECT (drop),
+ GDK_MACOS_DROP (drop)->pasteboard,
+ content_formats,
+ io_priority,
+ cancellable,
+ callback,
+ user_data);
+}
+
+static GInputStream *
+gdk_macos_drop_read_finish (GdkDrop *drop,
+ GAsyncResult *result,
+ const char **out_mime_type,
+ GError **error)
+{
+ return _gdk_macos_pasteboard_read_finish (G_OBJECT (drop), result, out_mime_type, error);
+}
+
+static void
+gdk_macos_drop_finish (GdkDrop *drop,
+ GdkDragAction action)
+{
+ g_assert (GDK_IS_MACOS_DROP (drop));
+
+ GDK_MACOS_DROP (drop)->finish_action = action;
+}
+
+static void
+gdk_macos_drop_finalize (GObject *object)
+{
+ GdkMacosDrop *self = (GdkMacosDrop *)object;
+
+ if (self->pasteboard)
+ {
+ [self->pasteboard release];
+ self->pasteboard = NULL;
+ }
+
+ G_OBJECT_CLASS (gdk_macos_drop_parent_class)->finalize (object);
+}
+
+static void
+gdk_macos_drop_class_init (GdkMacosDropClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GdkDropClass *drop_class = GDK_DROP_CLASS (klass);
+
+ object_class->finalize = gdk_macos_drop_finalize;
+
+ drop_class->status = gdk_macos_drop_status;
+ drop_class->read_async = gdk_macos_drop_read_async;
+ drop_class->read_finish = gdk_macos_drop_read_finish;
+ drop_class->finish = gdk_macos_drop_finish;
+}
+
+static void
+gdk_macos_drop_init (GdkMacosDrop *self)
+{
+}
+
+void
+_gdk_macos_drop_update_actions (GdkMacosDrop *self,
+ id<NSDraggingInfo> info)
+{
+ NSDragOperation op;
+ GdkDragAction actions = 0;
+
+ g_assert (GDK_IS_MACOS_DROP (self));
+
+ op = [info draggingSourceOperationMask];
+
+ if (op & NSDragOperationCopy)
+ actions |= GDK_ACTION_COPY;
+
+ if (op & NSDragOperationLink)
+ actions |= GDK_ACTION_LINK;
+
+ if (op & NSDragOperationMove)
+ actions |= GDK_ACTION_MOVE;
+
+ gdk_drop_set_actions (GDK_DROP (self), actions);
+}
+
+GdkMacosDrop *
+_gdk_macos_drop_new (GdkMacosSurface *surface,
+ id<NSDraggingInfo> info)
+{
+ GdkDrag *drag = NULL;
+ GdkContentFormats *content_formats;
+ GdkMacosDrop *self;
+ GdkDisplay *display;
+ GdkDevice *device;
+ GdkSeat *seat;
+
+ g_return_val_if_fail (GDK_IS_MACOS_SURFACE (surface), NULL);
+ g_return_val_if_fail (info != NULL, NULL);
+
+ display = gdk_surface_get_display (GDK_SURFACE (surface));
+ seat = gdk_display_get_default_seat (display);
+ device = gdk_seat_get_pointer (seat);
+ drag = _gdk_macos_display_find_drag (GDK_MACOS_DISPLAY (display), [info draggingSequenceNumber]);
+
+ content_formats = _gdk_macos_pasteboard_load_formats ([info draggingPasteboard]);
+
+ self = g_object_new (GDK_TYPE_MACOS_DROP,
+ "device", device,
+ "drag", drag,
+ "formats", content_formats,
+ "surface", surface,
+ NULL);
+
+ self->pasteboard = [[info draggingPasteboard] retain];
+
+ _gdk_macos_drop_update_actions (self, info);
+
+ gdk_content_formats_unref (content_formats);
+
+ return g_steal_pointer (&self);
+}
+
+NSDragOperation
+_gdk_macos_drop_operation (GdkMacosDrop *self)
+{
+ if (self->preferred_action & GDK_ACTION_LINK)
+ return NSDragOperationLink;
+
+ if (self->preferred_action & GDK_ACTION_MOVE)
+ return NSDragOperationMove;
+
+ if (self->preferred_action & GDK_ACTION_COPY)
+ return NSDragOperationCopy;
+
+ return NSDragOperationNone;
+}
'gdkmacosdisplay-settings.c',
'gdkmacosdisplay-translate.c',
'gdkmacosdrag.c',
+ 'gdkmacosdrop.c',
'gdkmacosdragsurface.c',
'gdkmacosglcontext.c',
'gdkmacoseventsource.c',